﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using DataBaseLayer.Dto;
using GrigSoft.Constants.Net.FTP;
using GrigSoft.Managers.Abstractions.Interfaces.IO;
using GrigSoft.Managers.Abstractions.Interfaces.Net;
using Peresvet_CMS.Entities;
using Peresvet_CMS.Resources;

namespace Peresvet_CMS.Managers
{
	public class GalleryManager
	{
		#region Variables

		private readonly IDirectoryManager _directoryManager;
		private readonly IFileManager _fileManager;
		private readonly IFTPManager _ftpManagerForBigImages;
		private readonly IFTPManager _ftpManagerForSmallImages;

		#endregion

		#region Constructors

		public GalleryManager(IDirectoryManager directoryManager, IFileManager fileManager,
			IFTPManager ftpManagerForBigImages, IFTPManager ftpManagerForSmallImages)
		{
			if (directoryManager == null)
				throw new ArgumentNullException(string.Format("directory Manager"));
			_directoryManager = directoryManager;

			if (fileManager == null)
				throw new ArgumentNullException(string.Format("file Manager"));
			_fileManager = fileManager;

			if (ftpManagerForBigImages == null)
				throw new ArgumentNullException(string.Format("ftp Manager For Big Images"));
			_ftpManagerForBigImages = ftpManagerForBigImages;

			if (ftpManagerForSmallImages == null)
				throw new ArgumentNullException(string.Format("ftp Manager For Small Images"));
			_ftpManagerForSmallImages = ftpManagerForSmallImages;
		}

		#endregion

		#region Methods

		public string CheckUploadingImages(string smallImagesFolderPath, string bigImagesFolderPath)
		{
			var result = new StringBuilder();

			if (!Directory.Exists(smallImagesFolderPath) || !Directory.Exists(bigImagesFolderPath))
				return string.Format("Отсутствие одной или нескольких директорий!");

			var bigImages = _directoryManager.GetImageFilePathesFromDirectory(bigImagesFolderPath);
			var smallImages = _directoryManager.GetImageFilePathesFromDirectory(smallImagesFolderPath);

			if (bigImages == null || smallImages == null
			    || !bigImages.Any() || !smallImages.Any())
				return string.Format("Ни одна из директорий не должна быть пустой!");

			var bigImageNames = _fileManager.GetFileNamesByFilePathes(bigImages);
			var smallImageNames = _fileManager.GetFileNamesByFilePathes(smallImages);

			if (bigImageNames == null || smallImageNames == null
				|| !bigImageNames.Any() || !smallImageNames.Any())
				return string.Format("Ошибка чтения имен изображений!");

			var missingSmallImages = smallImageNames.Where(si => !bigImageNames.Contains(si));
			var missingBigImages = bigImageNames.Where(bi => !smallImageNames.Contains(bi));

			foreach (var missingBigImage in missingBigImages)
			{
				result.AppendFormat("Отсутствует маленькое изображение для {0}", missingBigImage);
				result.AppendLine();
			}
			foreach (var missingSmallImage in missingSmallImages)
			{
				result.AppendFormat("Отсутствует основное изображение для {0}", missingSmallImage);
				result.AppendLine();
			}

			return result.ToString();
		}

		public IEnumerable<ImageItem> GetValidImageItems(string smallImagesFolderPath, string bigImagesFolderPath)
		{
			if (!Directory.Exists(smallImagesFolderPath) || !Directory.Exists(bigImagesFolderPath))
				return null;

			var bigImages = _directoryManager.GetImageFilePathesFromDirectory(bigImagesFolderPath);
			var smallImages = _directoryManager.GetImageFilePathesFromDirectory(smallImagesFolderPath);

			if (bigImages == null || smallImages == null
			    || !bigImages.Any() || !smallImages.Any())
				return null;

			var bigImageNames = _fileManager.GetFileNamesByFilePathes(bigImages);
			var smallImageNames = _fileManager.GetFileNamesByFilePathes(smallImages);

			if (bigImageNames == null || smallImageNames == null
			    || !bigImageNames.Any() || !smallImageNames.Any())
				return null;

			var validImageNames = bigImageNames.Where(bi => smallImageNames.Contains(bi)).ToList();
			if (!validImageNames.Any())
				return null;

			return validImageNames
				.Where(vin => !string.IsNullOrWhiteSpace(vin))
				.Select(vin => new ImageItem
				{
					BigImageFilePath = bigImages.SingleOrDefault(bi => bi.EndsWith(string.Format(@"\{0}", vin))),
					SmallImageFilePath = smallImages.SingleOrDefault(si => si.EndsWith(string.Format(@"\{0}", vin)))
				})
				.Where(ii => !string.IsNullOrWhiteSpace(ii.BigImageFilePath) && !string.IsNullOrWhiteSpace(ii.SmallImageFilePath))
				.ToList();
		}

		public bool SaveImage(string smallFilePath, string bigFilePath, int galleryId)
		{
			var smallFileContent = _fileManager.GetFileContent(smallFilePath);
			var bigFileContent = _fileManager.GetFileContent(bigFilePath);

			if (smallFileContent != null && bigFileContent != null)
			{
				var smallFileExt = _fileManager.GetFileExtension(smallFilePath);
				var bigFileExt = _fileManager.GetFileExtension(bigFilePath);

				if (!string.IsNullOrWhiteSpace(smallFileExt) && !string.IsNullOrWhiteSpace(bigFileExt))
				{
					string nextSmallImageName;
					string nextBigImageName;
					var nextImageNumber = AppContext.ServiceFactory.GalleriesService.GetLastImageNumber();
					do
					{
						nextImageNumber++;
						nextSmallImageName = string.Concat(nextImageNumber, smallFileExt);
						nextBigImageName = string.Concat(nextImageNumber, bigFileExt);
					} while (_ftpManagerForSmallImages.IsFileExistsOnFtp(nextSmallImageName)
						&& _ftpManagerForBigImages.IsFileExistsOnFtp(nextBigImageName));

					var uploadOnFtpRes = string.Empty;
					if (!string.IsNullOrWhiteSpace(nextSmallImageName))
						uploadOnFtpRes = _ftpManagerForSmallImages.UploadFileToFtp(smallFileContent, nextSmallImageName);
					if (!uploadOnFtpRes.Trim()
						.Equals(FtpResponseStatusDescriptions.UPLOAD_FILE_FROM_FTP_SUCCESSFUL_STATUS_DESCRIPTION,
							StringComparison.OrdinalIgnoreCase))
						return false;

					uploadOnFtpRes = string.Empty;
					if (!string.IsNullOrWhiteSpace(nextBigImageName))
						uploadOnFtpRes = _ftpManagerForBigImages.UploadFileToFtp(bigFileContent, nextBigImageName);
					if (!uploadOnFtpRes.Trim()
						.Equals(FtpResponseStatusDescriptions.UPLOAD_FILE_FROM_FTP_SUCCESSFUL_STATUS_DESCRIPTION,
							StringComparison.OrdinalIgnoreCase))
						return false;

					var newImage = new ImageData
					{
						GalleryId = galleryId,
						Url = string.Format(@"Images\Galleries\{0}", nextBigImageName),
						UrlThumb = string.Format(@"Images\SmallGalleries\{0}", nextSmallImageName)
					};
					AppContext.ServiceFactory.GalleriesService.CreateImage(newImage);
				}
			}

			return true;
		}

		public bool DeleteImage(int imageId)
		{
			try
			{
				var bigImageName = AppContext.ServiceFactory.GalleriesService.GetBigImageNameById(imageId);
				var smallImageName = AppContext.ServiceFactory.GalleriesService.GetSmallImageNameById(imageId);

				var result = FtpResponseStatusDescriptions.DELETE_FILE_FROM_FTP_SUCCESSFUL_STATUS_DESCRIPTION;
				if (!string.IsNullOrWhiteSpace(bigImageName))
					result = _ftpManagerForBigImages.IsFileExistsOnFtp(bigImageName)
						? _ftpManagerForBigImages.DeleteFileFromFtp(bigImageName)
						: FtpResponseStatusDescriptions.DELETE_FILE_FROM_FTP_SUCCESSFUL_STATUS_DESCRIPTION;

				if (result.Trim().Equals(FtpResponseStatusDescriptions.DELETE_FILE_FROM_FTP_SUCCESSFUL_STATUS_DESCRIPTION,
					StringComparison.OrdinalIgnoreCase))
				{
					if (!string.IsNullOrWhiteSpace(smallImageName))
						result = _ftpManagerForSmallImages.IsFileExistsOnFtp(smallImageName)
							? _ftpManagerForSmallImages.DeleteFileFromFtp(smallImageName)
							: FtpResponseStatusDescriptions.DELETE_FILE_FROM_FTP_SUCCESSFUL_STATUS_DESCRIPTION;

					if (result.Trim().Equals(FtpResponseStatusDescriptions.DELETE_FILE_FROM_FTP_SUCCESSFUL_STATUS_DESCRIPTION,
						StringComparison.OrdinalIgnoreCase))
					{
						AppContext.ServiceFactory.GalleriesService.DeleteImage(imageId);
						return true;
					}
				}
			}
			catch (Exception)
			{
				return false;
			}
			return false;
		}

		#endregion
	}
}
